#! /usr/bin/perl -w
#
# C. Junghans
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
#
# This is a clone for epslatex term and standalone input tex files of
# fixpslatex.pl by Sandro Wenzel, Thomas Vogel (November 2003)
# wenzel@itp.uni-leipzig.de or vogel@itp.uni-leipzig.de
#
#
#version 1.1f - removes trash tex files etc.
#version 1.2  - latex is now halt-on-errors
#version 1.3  - fixes problem with .tex file as input and some nicer perl
#version 1.4 - fixes problem with the pattern for size2 and add --debug option
#version 1.5 - fixes small problems with set out and set term
#version 1.5.1 - added -gv option
#version 1.6   added short better short opts
#version 1.7   added --gnuplot and --gversion
#version 1.7.1 added --watch to gv
#version 1.7.2 removed base name
#version 1.7.3 add --keep
#version 1.7.4 added tex package color (gnuplot < 4.2)
#version 1.7.5,  25.04.08 -- better version system
#version 1.7.6,  02.06.08 -- bug in --keep
#version 1.7.7,  06.06.08 -- added space in pattern for numbers
#version 1.7.8,  08.07.08 -- fixes a bug when calling itself and comment lines in gp file
#version 1.7.9,  13.10.08 -- added GPL header
#version 1.7.10, 01.06.09 -- improved docu
#version 1.7.11, 08.06.09 -- use bbox_add.pl from cwd, if it exists
#version 1.7.12, 30.06.09 -- added --gnuplot to oldcommandline 
#version 1.7.13, 18.07.09 -- fixed some typos in --help 
#version 1.7.14, 16.11.09 -- filecheck before scale calc, better when no arg given 
#version 1.8.0,  20.05.10 -- added --deps
#version 1.8.1,  01.06.10 -- added --bbox_add
#version 1.8.2,  03.07.10 -- fixed a bug in --deps
#version 1.8.3,  12.12.10 -- added --showheader and --headerfile option
#version 1.8.4,  21.03.11 -- --gv -> --view and improved --headerfile
#version 2.0.0,  06.04.11 -- major rework, trashed a lot of the old crap
#version 2.0.1,  23.05.11 -- bug fix (-r was not parsed) + dvips bug for textwi > 16cm
#version 2.0.2,  24.05.11 -- remove gnuplots pdfmarks 
#version 2.0.3,  24.05.11 -- added --multi and also XXX% in --textwidth
#version 2.1.0,  27.05.11 -- removed --fontscale, too confusing
#version 2.1.1,  18.11.11 -- added support for load in --deps
#version 2.1.2,  22.03.12 -- allow additonal options in plotfile (#GP2EPS)
#version 2.1.2,  10.04.12 -- fixed dvips bug, which lead to eps upside-down
#version 2.2.0,  11.04.12 -- removed --scale option as --multi has replaced it
#version 2.2.1,  04.05.12 -- only allow one option per #GP2EPS line
#version 2.2.2,  13.08.13 -- added deps= to deps
#version 2.2.3,  21.08.13 -- added --adddep
#version 2.2.4,  20.09.13 -- tmpfile contain $$ to allow parallel build in make
#version 2.2.5,  19.12.13 -- fixed default width
#version 2.3.0,  11.12.14 -- added pdf output format using gc

use strict;

$_=$0;
s#^.*/##;
my $progname=$_;
my $usage="Usage: $progname [OPTIONS] FILE\nHelp with --help";

#Defaults
my $quiet=undef;
my $outname=undef;
my $outext="eps";
my $ratioscale=1.0;
my $pointsize=10;
my $gpown=10;
my $term="set terminal epslatex standalone";
my $termopts="color";
my @margins;
my @multi=(1,1);
my $debug=undef;
my $force=undef;
my $gnuplot="gnuplot";

my $viewer=undef;
my $showdeps=undef;
my $deps="";
my $widthfile=undef;
my $width=8.3;
my $ratio=1.42857143;
my $tmpfile="gp2eps_tmp-$$";

sub run_latex($;$) {
  die "Could not find tex file '$_[0]'\n" unless( -f "$_[0]" );
  die "tex file $_[0] does not end on .tex\n" unless $_[0] =~ /^(.*)\.tex$/;
  my $trunc="$1";
  my $path=":";
  if ($_[1]){
    die "Could not find dir '$_[1]'\n" unless ( -d "$_[1]" );
    $path.=$_[1];
  }
  die "Error at running 'latex $_[0]' see $trunc.log for error\n" if system("export TEXINPUTS='$path'; echo | latex -halt-on-error $_[0] > /dev/null 2> /dev/null");
  unlink("$trunc.aux");
  unlink("$trunc.log");
}

sub get_width($) {
  unlink("$tmpfile.tex") if $force;
  die "$tmpfile.tex is already and would be overwritten add --force if you are sue that you want that.\n" 
    if ( -r "$tmpfile.tex");
  open(TEXFILE,"> $tmpfile.tex") or die "can not open '$tmpfile.tex'\n";
  my $path=undef;
  $path=$1 if $_[0] =~ m{^(.*)/(.*?)$};
  open(HEADERFILE,$_[0]) or die "Error at opening widthfile '$_[0]'\n";
  while (<HEADERFILE>) {
      next if /^%/;
      next if /^\s*$/;
      next if /\\input/;
      last if /\\begin\{document\}/;
      print TEXFILE "$_";
  }
  close(HEADERFILE);
  print TEXFILE '\usepackage{layouts}'."\n";
  print TEXFILE '\begin{document}'."\n";
  print TEXFILE '\printinunitsof{cm}\prntlen{\columnwidth}'."\n";
  print TEXFILE '\end{document}'."\n";
  close(TEXFILE);
  run_latex("$tmpfile.tex",$path);
  unlink("$tmpfile.tex");
  open(DVIFILE,"$tmpfile.dvi") or die "Could not open '$tmpfile.dvi'\n";
  my $tl=undef;
  while (<DVIFILE>) {
    $tl = $1 if /([0-9.]+)cm/;
    last if defined($tl);
  }
  close(DVIFILE);
  die "Could not grep width from $tmpfile.dvi \n" unless defined($tl);
  unlink("$tmpfile.dvi");
  return $tl;
}

sub parse_opts(@) {
  my $l=$#_;
  while ((defined ($_[0])) and ($_[0] =~ /^\-/))
  {
          if (($_[0] !~ /^--/) and (length($_[0])>2)){
             $_=shift(@_);
             if ( $_ =~ /^-[foprs]/ ) {
                unshift(@_,substr($_,0,2),substr($_,2));
             }
             else{
                unshift(@_,substr($_,0,2),"-".substr($_,2));
             }
          }
  	if (($_[0] eq "-h") or ($_[0] eq "--help"))
  	{
  		print <<END;
$usage
Makes a eps file out of a gnuplot script
-v, --version         Prints version
    --gversion        Show gnuplot version (may use --gnuplot before)
-h, --help            Show this help message
-q, --quiet           Do not show messages
                      except errors
-p, --pointsize X.X   pointsize of the fonts
                      default: $pointsize
    --ratioscale X.X  change the ratio between size of labels
                      (\\gplabel) and numbers (\\gpnumber)
                      default: $ratioscale
-w, --width     X.X   width (in cm) of tex docment (use --widthfile if unknown)
                      default: $width cm (usually columnwidth, for 1 column = textwidth)
-r, --ratio     X.X   ratio of the image (width/heigth)
                      default: $ratio	   
    --margin XXX      margin of the images of the image (comma separeted numbers l,r,t,b - empty = auto)
                      default: auto
    --multi XXX       This is a multiplot (comma separated number x,y), scales width and heigth
		      default: $multi[0],$multi[1]	   
    --widthfile FILE  Get columnwidth from this latex file
-o, --output FILE     give the output filename
                      default: trunc of 1st gnuplot script
    --gpown  X.X      give size of additional label '\\gpown'
                      default: $gpown
    --termopts OPTS   extra options to be given to '$term'
                      default: $termopts
    --view VIEWER     view output with VIEWER at the end
    --deps            show makefile rule for the eps file (implies --quiet)
    --adddep FILE     add FILE to dependency rule in --deps
    --gnuplot CMD     change the gnuplot command
                      default: "$gnuplot"
    --force           force overwritting of all intermediate files
    --debug           keep .tex file for debugging

Axis numbers are always scaled with 0.8 (change with -r option). Additional stuff to scale
like the graph numbers can be marked with \\gpnumber.  Stuff to scale like labels can be
marked with \\gplabel. Stuff to scale somehow else can be marked with \\gpown (use --gpown).

Report bugs and comments at https://code.google.com/p/gnuplotutils/issues/list
                         or junghans\@votca.org
END
  		exit;
  	}
  	elsif (($_[0] eq "-o") or ($_[0] eq "--output"))
  	{
  		shift(@_);
  		$outname=shift(@_);
		$outname =~ /^(.*)\.([^.]*)?/ or die "File '$outname' has no extension\n";
		$outname = "$1";
		$outext = "$2";
		die "Only extensions eps and pdf are implemented yet (found $outext)\n" unless ($outext =~ /(eps|pdf)/);
  	}
  	elsif (($_[0] eq "-v") or ($_[0] eq "--version"))
  	{
  		my $version=`perl -ne 'print "\$1\n" if /^#(version .*?) --/' $0 | perl -ne 'print if eof'`;
  		chomp($version);
  		print "$progname, $version  by C. Junghans\n";
  		exit;
  	}
  	elsif ($_[0] eq "--hg")
  	{
  		my $message=`perl -ne 'print "\$1\n" if /^#version .*? -- (.*)\$/' $0 | perl -ne 'print if eof'`;
  		chomp($message);
  		print "$progname: $message\n";
  		exit;
  	}
  	elsif (($_[0] eq "-q") or ($_[0] eq "--quiet"))
  	{
  		$quiet='yes';
  		shift(@_);
  	}
  	elsif (($_[0] eq "-p") or ($_[0] eq "--pointsize"))
  	{
  		shift(@_);
  		$pointsize=shift(@_);
  	}
  	elsif ($_[0] eq "--ratioscale")
  	{
  		shift(@_);
  		$ratioscale=shift(@_);
  	}
  	elsif (($_[0] eq "-r") or ($_[0] eq "--ratio"))
  	{
  		shift(@_);
  		$ratio=shift(@_);
  	}
  	elsif (($_[0] eq "-w") or ($_[0] eq "--width"))
  	{
  	  shift(@_);
  	  $width=shift(@_);
  	}
  	elsif ($_[0] eq "--widthfile")
  	{
  	  shift(@_);
  	  $widthfile=shift(@_);
  	  die "File '$widthfile' not found\n" unless ( -f "$widthfile" );
  	}
  	elsif ($_[0] eq "--view")
  	{
  		shift(@_);
  		$viewer=shift(@_);
  	}
  	elsif ($_[0] eq "--gpown")
  	{
  		shift(@_);
  		$gpown=shift(@_);
  	}
  	elsif ($_[0] eq "--termopts")
  	{
  		shift(@_);
  		$termopts=shift(@_);
  	}
  	elsif ($_[0] eq "--margins")
  	{
  		shift(@_);
                  @margins=split(/,/,shift(@_).",0");
  		die "Not enough values after --margins, I got $#margins, but need 4\n" if $#margins < 4;
  	}
  	elsif ($_[0] eq "--multi")
  	{
  		shift(@_);
                  @multi=split(/,/,shift(@_).",1");
  		die "Not enough values after --multi, I got $#multi, but need 2\n" if $#multi < 2;
  	}
  	elsif ($_[0] eq "--deps")
  	{
  		shift(@_);
  		$showdeps='yes';
  		$quiet="yes";
  	}
  	elsif ($_[0] eq "--adddep")
  	{
  		shift(@_);
		$deps.=" ".shift(@_);
  	}
  	elsif ($_[0] eq "--gnuplot")
  	{
  		shift(@_);
  		$gnuplot=shift(@_);
  	}
  	elsif ($_[0] eq "--gversion")
  	{
  		system("echo show version | $gnuplot");
  		exit;
  	}
  	elsif ($_[0] eq "--debug")
  	{
  		shift(@_);
  		$debug='yes';
  		$force='yes';
  	}
  	elsif ($_[0] eq "--force")
  	{
  		shift(@_);
  		$force='yes';
  	}
  	else
  	{
  		die "Unknow option '".$_[0]."'!\n";
  	}
  }
  return $l-$#_;
}

###############
# MAIN PROGAM #
###############
my $s=parse_opts(@ARGV);
while ($s-- > 0) {shift(@ARGV)};

#Print usage
die "No file given\n$usage\n" unless $#ARGV > -1;
die "File '$ARGV[0]' does not exist or is not readable\n" unless (-r $ARGV[0]);

print "Using pointsize=$pointsize and gpown=$gpown\n" unless $quiet;
print "Using gnuplot: $gnuplot\n" unless $quiet;
my $size=$pointsize;
my $sizestart='{\fontsize{'.$size.'}{'.$size.'}\selectfont';
print "$sizestart\n" if $debug;
my $size2=$pointsize*$ratioscale;
my $size2start='{\fontsize{'.$size2.'}{'.$size2.'}\selectfont';
print "$size2start\n" if $debug;
my $size3=$gpown;
my $size3start='{\fontsize{'.$size3.'}{'.$size3.'}\selectfont';
print "$size3start\n" if $debug;

print "Using gnuplot script: '$ARGV[0]'\n" unless $quiet;
$ARGV[0] =~ /^(.*)\.[^.]*?/ or die "File '$ARGV[0]' has no extension\n";
$outname="$1" unless $outname;

#look for additional opts in plot file
open(FILE,$ARGV[0]) or die "Error at opening gp file '$ARGV[0]'\n";
while (<FILE>) {
  if (s/^#GP2EPS\s+(-\S+)//) {
    my @opts;
    chomp($_);
    #treat the rest of the line as argument of the option
    push(@opts,$1,$_);
    print "Inside plotfile options: @opts\n" unless $quiet;
    parse_opts(@opts);
  }
}
close(FILE);

#show deps for makefiles, we need $output name
if ($showdeps)
{
  $deps="$outname.$outext: $ARGV[0] $deps";
  my @files;
  push(@files,$ARGV[0]);
  while (defined(my $file=pop(@files))) {
    open(FILE,$file) or die "Error at opening gp file '$file'\n";
    while (<FILE>)
    {
      #in gp file
      #concat line ending with \
      while ((/(.*)\\$/) and defined(my $line=<FILE>))
      {
      	$_=$1.$line;
      }
      #ignore comment lines
      next if /^#/;
      #line starting with plot, splot, replot
      if (/^\s*(re|s)?plot/)
      {
         #save old line, we cannot be sure there is not includegraphics in plot command
      	 my $line=$_;
      	 #plot [xx:xx] or , can stand before filename in "" or ''
      	 while (s/(?:plot(?:\s*\[.*\])?|,)\s*(['"])([^\1]*?)(\1)//)
      	 {
      	   #and inline command "<xxx " should be ignored
      	   $deps.=" $2" if ($2 !~ /^</);
      	 }
      	 $_=$line;
      }
      #?: in (?:\[.*?\]) means: don't name it \1
      if (/includegraphics(?:\[.*?\])?\{(.*?)\}/) {
      	$deps.=" $1";
      }
      if (/load\s*(['"])([^\1]*?)(\1)/) {
	die "Cirular deps (multiple times $1)\n" if ($deps =~ / ($2) /);
      	$deps.=" $2";
	push(@files,$2);
      }
    }
  }
  print "$deps\n";
  exit;
}

if ($widthfile) {
  $width=get_width($widthfile);
  print "Columnwidth determined from $widthfile is $width cm\n" unless $quiet
}else{
  print "Columnwidth is $width cm\n" unless $quiet;
}

#build tex file from gnuplot
open(FILE,$ARGV[0]) or die "Error at opening gp file '$ARGV[0]'\n";
unlink("$tmpfile.gp") if $force;
die "$tmpfile.gp is already and would be overwritten add --force if you are sue that you want that.\n" if ( -r "$tmpfile.gp");
open(NEWFILE,"> $tmpfile.gp") or die "Error at opening gp new file '$tmpfile.gp'\n";
my $w=$multi[0]*$width."cm";
my $h=$multi[1]*$width/$ratio."cm";
print "Image will have the size $w x $h\n" unless $quiet;
print NEWFILE "$term size $w,$h $size $termopts\n";
print "Terminal line is: $term size $w,$h $size $termopts\n";
print NEWFILE "set output '$tmpfile.tex'\n";
if (@margins) {
  print NEWFILE "set lmargin ".shift(@margins)."\n";
  print NEWFILE "set rmargin ".shift(@margins)."\n";
  print NEWFILE "set tmargin ".shift(@margins)."\n";
  print NEWFILE "set bmargin ".shift(@margins)."\n";
}
while (<FILE>)
{
  	#ignore term and outline in gp file
	next if (/set (out |ou |output)/);
	next if (/set (t |term |terminal)/);
	print NEWFILE $_;
}
close(FILE);
close(NEWFILE);

die "Error at running 'gnuplot $tmpfile.gp'\n" if system ("$gnuplot $tmpfile.gp");
unlink("$tmpfile.gp") unless $debug;

print "Output file : '$outname.$outext'\n" unless $quiet;

open (NEWTEXFILE,"> $outname.tex") or die "Error at opening new tex file\n";
open(OLDTEXFILE,"$tmpfile.tex")	or die "Error at opening old tex file\n";
unlink("$tmpfile.cfg") if $force;
die "$tmpfile.cfg is already and would be overwritten add --force if you are sue that you want that.\n" if ( -r "$tmpfile.cfg");
open (CONFFILE,"> $tmpfile.cfg") or die "Error at opening new tex file\n";
print CONFFILE '\usepackage{amsmath}'."\n";
print CONFFILE '\usepackage{psfrag}'."\n";
print CONFFILE '\newcommand{\gplabel}{}'."\n";
print CONFFILE '\newcommand{\gpnumber}{}'."\n";
print CONFFILE '\newcommand{\gpown}{}'."\n";

#Disable as it has other side effects
#http://www.cs.toronto.edu/~dross/latex/
#print CONFFILE '\special{! TeXDict begin /landplus90{true}store end }'."\n";
close(CONFFILE);

open (EPSFILE, "$tmpfile-inc.eps") or die "Error at opening '$tmpfile-inc.eps'\n"; 
open (NEWEPSFILE, "> $tmpfile-inc2.eps") or die "Error at opening '$tmpfile-inc.eps'\n"; 
while (<EPSFILE>) {
  #remove gnuplot nasty pdfmarks
  s/\s*\/(Subject|Creator|Author|CreationDate)\s+\(.*\)/% $& #disabled by GP2EPS/;
  s/\s*\/DOCINFO\s+pdfmark/% $& #disabled by GP2EPS/;
  print NEWEPSFILE $_;
}
close(EPSFILE);
close(NEWEPSFILE);
unlink("$tmpfile-inc.eps") unless $debug;

my @sizelines;
my @size2lines;
my @size3lines;
my $put=undef;
while (<OLDTEXFILE>)
{
	s/gnuplot\.cfg/$tmpfile\.cfg/;
	#Has strange side effects
	#s/\\usepackage\[(.*)\]{geometry}/\\usepackage[dvips,$1]{geometry}/;
	s/$tmpfile-inc/$&2/;
	# in the put block of the tex file
	if ( $_ =~ /\\put/ )
	{
		$put='yes';
		if ($_ =~/\\gplabel/)
		{
			push (@sizelines,$_);
		}
		elsif ($_ =~/\\gpnumber/)
		{
			push (@size2lines,$_);
		}
		elsif ($_ =~/\\gpown/)
		{
			push (@size3lines,$_);
		}
		elsif ( $_ =~ /\{\}\s*[\de+-.]*\s*\}\}%\n$/ )
		{
			push (@size2lines,$_);
		}
		else
		{
			push (@sizelines,$_);
		}
	}
	else
	{
		if ($put)
		{
			if ($#sizelines>-1)
			{
				print NEWTEXFILE $sizestart,"\n";
				while (my $i=pop(@sizelines))
				{
					print NEWTEXFILE $i;
				}
				print NEWTEXFILE "}\n";
			}
			if ($#size2lines>-1)
			{
				print NEWTEXFILE $size2start,"\n";
				while (my $i=pop(@size2lines))
				{
					print NEWTEXFILE $i;
				}
				print NEWTEXFILE "}\n";
			}
			if ($#size3lines>-1)
			{
				print NEWTEXFILE $size3start,"\n";
				while (my $i=pop(@size3lines))
				{
					print NEWTEXFILE $i;
				}
				print NEWTEXFILE "}\n";
			}
		}
		$put=undef;
		print NEWTEXFILE $_ unless $_ =~ /\\endinput/
	}
}
close(NEWTEXFILE);
close(OLDTEXFILE);
unlink("$tmpfile.tex") unless $debug;

run_latex("$outname.tex");
unlink("$tmpfile.cfg") unless $debug;
unlink("$outname.tex") unless $debug;

my $dvips="dvips -T $w,$h -o $outname.eps $outname.dvi";
print "Running: '$dvips'\n" unless $quiet;
die "Error at running dvips \n" if system("$dvips > /dev/null 2> /dev/null");
unlink("$outname.dvi") unless $debug;
unlink("$tmpfile-inc2.eps") unless $debug;

if ($outext eq "pdf"){
  my $gscmd="gs -sDEVICE=pdfwrite -o $outname.pdf $outname.eps";
  print "Running: '$gscmd'\n" unless $quiet;
  die "Error at running gs \n" if system("$gscmd > /dev/null 2> /dev/null");
  unlink("$outname.eps") unless $debug;
}

if ($viewer)
{
	die "Error at running $viewer\n" if system("$viewer $outname.eps &");
}
